﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Rappelz.GameServer
{
    public class ArRegion
    {
// UserDefinedType: ArRegion
// Function       :   public void ArRegion(const struct ArRegion &)
// Function       :   public void ArRegion::ArRegion()
// Function       :   public void ArRegion::~ArRegion()
// Function       :   public void AddStaticObject(struct ArObject *)
// Function       :   public void AddMovableObject(struct ArObject *)
// Function       :   public void AddClientObject(struct ArObject *)

        public void AddObject(BaseObject obj)
        {
            List<BaseObject> lbo = null;

            if (obj.m_nArObjectType != 0)
            {
                if (obj.m_nArObjectType == 1)
                {
                    lbo = this.m_vMOVABLEObject;
                }
                else
                {
                    if (obj.m_nArObjectType != 2 )
                        return;
                    lbo = this.m_vClientObject;
                }
            }
            else
            {
                lbo = this.m_vStaticObject;
            }
            obj.region_x = this.x;
            obj.region_y = this.y;
            lock(vLock)
            {
                this.addObject(obj, lbo);
            }
            
        }
// Function       :   public void RemoveStaticObject(struct ArObject *)
// Function       :   public void RemoveMovableObject(struct ArObject *)
// Function       :   public void RemoveClientObject(struct ArObject *)

        public void RemoveObject(BaseObject obj)
        {
            List<BaseObject> lbo = null;

            if (obj.m_nArObjectType != 0)
            {
                if (obj.m_nArObjectType == 1)
                {
                    lbo = this.m_vMOVABLEObject;
                }
                else
                {
                    if (obj.m_nArObjectType != 2)
                        return;
                    lbo = this.m_vClientObject;
                }
            }
            else
            {
                lbo = this.m_vStaticObject;
            }
            this.removeObject(obj, lbo);
        }

// Function       :   public unsigned int ClientCount()

        public uint DoEachClient(BaseObjectFunctor fn)
        {
            lock(vLock)
            {
                foreach (BaseObject obj in this.m_vClientObject)
                {
                    fn.run(obj);
                }
                return (uint)this.m_vClientObject.Count;
            }
        }

        public uint DoEachStaticObject(BaseObjectFunctor fn)
        {
            lock (vLock)
            {
                foreach (BaseObject obj in this.m_vStaticObject)
                {
                    fn.run(obj);
                }
                return (uint)this.m_vStaticObject.Count;
            }
        }


        public uint DoEachMovableObject(BaseObjectFunctor fn)
        {
            lock (vLock)
            {
                foreach (BaseObject obj in this.m_vMOVABLEObject)
                {
                    fn.run(obj);
                }
                return (uint)this.m_vMOVABLEObject.Count;
            }
        }

        public uint x;                  // 0x0
        public uint y;                  // 0x4
        public byte layer;              // 0x8

        public void addObject(BaseObject obj, List<BaseObject> v)
        {
//            debug_region_list(v);
            lock(v)
            {
                try
                {
                    FieldProp fp = obj as FieldProp;
                    if(fp != null)
                    {
                        if(fp.m_PropInfo.nPropId == 300064)
                        {
                            Globals.Log.Info("Added Pillar Of Light");
                        }
                    }
                    v.Add(obj);
                    obj.region_index = v.Count - 1;
                    //            debug_region_list(v);
                    obj.bIsInWorld = true;
                    obj.pRegion = this;
                }
                catch (System.Exception ex)
                {
                    Globals.Log.Error("addObject Exception: {0}", ex);
                }
            }
        }

        public void removeObject(BaseObject obj, List<BaseObject> v)
        {
            lock(vLock)
            {
                //            debug_region_list(v);
                if (v.Count == 0)
                {
                    Globals.Log.Error("RemoveObject Error 1");
                }
                if (!ReferenceEquals(v[obj.region_index], obj))
                {
                    Globals.Log.Error("RemoveObject Error 2");
                }
                if (!ReferenceEquals(v.Last(), obj))
                {
                    BaseObject lbo = v.Last();
                    v[obj.region_index] = lbo;
                    lbo.region_index = obj.region_index;
                }
                v.RemoveAt(v.Count - 1);
                obj.region_index = -1;
                obj.pRegion = null;
                obj.bIsInWorld = false;
                //            debug_region_list(v);
            }
        }

        public List<BaseObject> m_vStaticObject = new List<BaseObject>();              // 0xC 
        public List<BaseObject> m_vMOVABLEObject = new List<BaseObject>();              // 0x1C 
        public List<BaseObject> m_vClientObject = new List<BaseObject>();              // 0x2C 
        public object vLock = new object();
// Function       :   public struct ArRegion & operator=(const struct ArRegion &)
// Function       :   public void * __vecDelDtor(unsigned int)

    }
}
